package com.tbit.uqbike.client.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tbit.common.constant.OperationPlatform;
import com.tbit.common.constant.OrderLogConstant;
import com.tbit.common.entity.MachineOpLog;
import com.tbit.uqbike.client.business.machine_op_log.service.MachineOpLogService;
import com.tbit.uqbike.client.constant.*;
import com.tbit.uqbike.client.constant.enums.ControlWay;
import com.tbit.uqbike.client.dao.core.AccountConfigExtDao;
import com.tbit.uqbike.client.dao.core.BleHelmetDao;
import com.tbit.uqbike.client.dao.ter.TerAttrExDao;
import com.tbit.uqbike.client.dao.ter.TerInfoDao;
import com.tbit.uqbike.client.exception.BaseException;
import com.tbit.uqbike.client.pojo.*;
import com.tbit.uqbike.client.pojo.newEntity.AccountConfigExt;
import com.tbit.uqbike.client.pojo.newEntity.BleHelmet;
import com.tbit.uqbike.client.pojo.newEntity.TerInfoUpload;
import com.tbit.uqbike.client.pojo.newEntity.WebcamInfo;
import com.tbit.uqbike.client.pojo.temppower.TempPowerMsg;
import com.tbit.uqbike.client.pojo.tlv.*;
import com.tbit.uqbike.client.service.*;
import com.tbit.uqbike.client.util.DateTimeUtil;
import com.tbit.uqbike.client.util.ObjectUtil;
import com.tbit.uqbike.client.util.RedisUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

@Service("terControlService")
public class TerControlServiceImpl implements TerControlService {

    private final static Logger log = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
    @Autowired
    private MQProducer mQProducer;
    @Autowired
    private MachineService machineService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private ParkMachineService parkMachineService;
    @Autowired
    private OrderLogService orderLogService;
    @Autowired
    private TerAttrExDao terAttrExDao;
    @Autowired
    private AccountUserService accountUserService;
    @Autowired
    private ParkPointService parkPointService;
    @Autowired
    private MachineCheckService machineCheckService;
    @Autowired
    private MachineBorrowService machineBorrowService;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private BleHelmetDao bleHelmetDao;
    @Autowired
    private ParkService parkService;
    @Autowired
    private UserWeightLogService userWeightLogService;
    @Autowired
    private UserDetailService userDetailService;
    @Autowired
    private UserService userService;
    @Autowired
    private AccountService accountService;
    @Autowired
    private MachineFunctionService machineFunctionService;
    @Autowired
    private RideLogServiceImpl rideLogService;
    @Autowired
    private AccountConfigExtDao accountConfigExtDao;
    @Resource
    private MachineOpLogService machineOpLogService;
    @Resource
    private MQProducer mqProducer;
    @Resource
    private TerInfoDao terInfoDao;

    @Override
    public void sendControl(String serNO, String machineNO, String controlType, String paramName, String paramValue,
                            Machine machine, boolean ble, Integer orderSource, Integer opId, String remark) {
        /**查询消息是在的队列名称*/
        String routeKey = redisService.getMain(RedisUtil.getTerHashId(machineNO), RedisConstant.REDIS_TER_ROUTE_KEY);
        if (StrUtil.isNotEmpty(routeKey)) {
            /**封装消息*/
            TerMsg termsg = new TerMsg();
            termsg.setSn(machineNO);
            termsg.setSerNO(serNO);
            termsg.setControlType(controlType);
            termsg.setParamName(paramName);//1上锁，11开锁
            termsg.setParamValue(paramValue);

            TerControlMsg terControlMsg = new TerControlMsg();
            terControlMsg.setFeedback(RabbitMQData.queueName);
            terControlMsg.setMsgId(GatewayProtocol.MQ_MSG_ID_CONTROL_TER);
            terControlMsg.setData(termsg);
            /**终端开锁，关锁重置静止事件为当前时间*/
            if (ControlTypeConstant.CONTROL_TYPE_LOCK.equals(paramName) || ControlTypeConstant.CONTROL_TYPE_UNLOCK.equals(paramName)
                    || ControlTypeConstant.CONTROL_TYPE_PARKRIDE.equals(paramName) || ControlTypeConstant.CONTROL_TYPE_CONTINUERIDE.equals(paramName)) {
                TerAttrEx terAttrEx = new TerAttrEx();
                terAttrEx.setDt(new Date());
                terAttrEx.setMachineNO(machine.getMachineNO());
                terAttrEx.setName("tLST");
                terAttrExDao.edit(terAttrEx);
            }

            /**发送到MQ*/
            mQProducer.sendToRide(RabbitMQData.queueExchange, routeKey, JSON.toJSONString(terControlMsg));

            /**添加到流水号到内存*/
            redisService.add(RedisConstant.ORDER_WEB_KEY_PREFIX + serNO, JSON.toJSONString(terControlMsg), 60);
            if (!ble) {
                orderSource = orderSource == null ? -1 : orderSource;
                OrderLog orderLog = new OrderLog();
                orderLog.setOrderSerNo(serNO);
                orderLog.setMachineId(machine.getMachineId());
                orderLog.setMachineNo(machine.getMachineNO());
                orderLog.setUserCode(machine.getUserCode());
                orderLog.setChannelType(Integer.valueOf(ControlWay.CLIENT_GPRS.getCode()));
                orderLog.setOpType(OrderLogTypeConstant.OPTYPE_USER);
                orderLog.setAccountUserId(machine.getAccountId());
                AccountUser accountUser;
                if ((OrderLogConstant.fromMain(orderSource) || OrderLogConstant.fromWeb(orderSource)) && (accountUser = accountUserService.getById(opId)) != null) {
                    orderLog.setAccountUserId(opId);
                    orderLog.setOpType(getAccountUserType(accountUser, orderSource));
                }
                if ("get".equalsIgnoreCase(controlType) || "set".equalsIgnoreCase(controlType)) {
                    orderLog.setBusinessType(-1);
                } else {
                    orderLog.setBusinessType(Integer.valueOf(paramName));
                }
                orderLog.setOpTime(DateTimeUtil.getNowTime());
                orderLog.setOrderContent(paramName);
                orderLog.setOrderSource(orderSource);
                orderLog.setOrderType(controlType);
                orderLog.setOpId(opId);
                orderLog.setRemark(remark);
                orderLogService.insert(orderLog);
                /**兼容rfid还车，记录车辆编号下发指令流水号*/
                redisService.add(RedisConstant.MACHINE_NO_SERNO + machine.getUserCode(), serNO, 60);
            }

        } else {
            /**兼容马蹄锁号段不提示错误*/
            if (machine != null && !machine.getUserCode().startsWith("901") && !machine.getUserCode().startsWith("902")) {
                throw new BaseException("-50004", "车辆远程操作失败");
            }
        }
    }


    @Override
    public void respHandle(String serNO, String controlRet) {
        /**根据流水号查询下发的信息*/
        String tmp = redisService.get(RedisConstant.ORDER_WEB_KEY_PREFIX + serNO);
        TerControlMsg terControlMsg = JSON.parseObject(tmp, TerControlMsg.class);
        if (terControlMsg != null) {
            String paramName = terControlMsg.getData().getParamName();
            /**判断是开锁还是解锁*/
            if (ControlTypeConstant.CONTROL_TYPE_LOCK.equals(paramName) || ControlTypeConstant.CONTROL_TYPE_PARKRIDE.equals(paramName)) {
                if (ControlTypeConstant.CONTROL_TYPE_SUCC.equals(controlRet)) {
                    /**上锁成功*/
                    log.info(String.format("[%s]上锁成功", terControlMsg.getData().getSn()));
                    String value = redisService.get(RedisConstant.REDIS_PAY_SIGN + serNO);
                    if (value == null) {
                        redisService.add(RedisConstant.REDIS_PAY_SIGN + serNO, "1", 10);
                        machineService.ter_lock(serNO);
                    }
                } else {
                    /**上锁失败*/
                    log.info(String.format("[%s]上锁失败", terControlMsg.getData().getSn()));

                    /**付款成功以后骑行中发送撤防和锁车指令*/
                    if (ControlTypeConstant.CONTROL_TYPE_MOVING.equals(controlRet)) {
                        log.info(String.format("[%s]上锁失败-车辆运动中", terControlMsg.getData().getSn()));
                        String redisSerNO = redisService.get(RedisConstant.REDIS_TER_PAY_FINISHORDER_SERNO + serNO);
                        if (redisSerNO != null && redisSerNO.equals(serNO)) {
                            /**给终端下发指令*/
                            String cfSerNO = UUID.randomUUID().toString();
                            Machine machine = machineService.getByMachineNO(terControlMsg.getData().getSn());

                            if (machine.getMachineType().equals(MachineStateConstant.MACHINE_TYPE_BIKE)) {
                                log.info(String.format("%s自行车不触发断电", machine.getMachineNO()));
                                return;
                            }
                            sendControl(cfSerNO, terControlMsg.getData().getSn(), ControlTypeConstant.CONTROL_TYPE_CONTROL, ControlTypeConstant.CONTROL_TYPE_UNSTART, "", machine, false, 1, 1, "车辆运动中-下发断电指令");
                            log.info(String.format("[%s]车辆运动中-下发断电指令", terControlMsg.getData().getSn()));
                        }
                    }
                }
                /**借还车指令回复信息推送到mq*/
                String brtInfo = redisService.get(serNO);
                if (brtInfo != null) {
                    BorrowReturnTer info = JSONObject.parseObject(brtInfo, BorrowReturnTer.class);
                    if (info.getType() == 0) {
                        //正常接还车
                        if (ControlTypeConstant.CONTROL_TYPE_SUCC.equals(controlRet)) {
                            send(info.getAccountId(), info.getUserId(), info.getMachineId(), null, GatewayProtocol.MQ_MSG_ID_RSP_SUCCESS,
                                    MachineStateConstant.MACHINE_TYPE_RETURN, GatewayProtocol.MQ_MSG_ID_AROUND_BR_RSP_PUSH);
                        } else {
                            /**借还车信息推送到mq*/
                            send(info.getAccountId(), info.getUserId(), info.getMachineId(), null, GatewayProtocol.MQ_MSG_ID_RSP_FAIL,
                                    MachineStateConstant.MACHINE_TYPE_RETURN, GatewayProtocol.MQ_MSG_ID_AROUND_BR_RSP_PUSH);

                        }
                    }
                }
            } else if (ControlTypeConstant.CONTROL_TYPE_UNLOCK.equals(paramName) || ControlTypeConstant.CONTROL_TYPE_CONTINUERIDE.equals(paramName) || ControlTypeConstant.CONTROL_TYPE_UNSTART.equals(paramName)) {
                String brtInfo = redisService.get(serNO);
                if (ControlTypeConstant.CONTROL_TYPE_SUCC.equals(controlRet)) {
                    /**开锁成功*/
                    log.info(String.format("编号【%s】开锁成功", terControlMsg.getData().getSn()));
                    machineService.ter_unlock(serNO);
                    Machine machine = machineService.getByMachineNO(terControlMsg.getData().getSn());
                    if (machine != null) {
                        parkService.delByMachineId(machine.getMachineId());
                        // 根据是超远距离借车 or 运营区外借车 ， 决定下发 临停指令 还是 临时通电指令
                        // 超远距离借车
                        String tooFarFlag = redisService.get(String.format(RedisConstant.TOO_FAR_BORROW_BIKE, machine.getMachineId()));
                        BorrowReturnTer info = JSONObject.parseObject(brtInfo, BorrowReturnTer.class);
                        if (Objects.equals(tooFarFlag,"1")){
                            String serNO_park = UUID.randomUUID().toString();
                            /**machineSofewareInfoMap中包含的软件版本号和终端上线时间大于20年8月1号认为支持新的临时停车语音*/
                            TerInfo terInfo = terInfoDao.getByMachineNO(machine.getMachineNO());
                            if (terInfo != null && (
                                    DateTimeUtil.getTimeDF("2020-08-01 00:00:00", terInfo.getJoinTime()) > 0 || SystemData.machineSofewareInfoMap.containsKey(terInfo.getSoftVersion()))) {
                                /**远程控制-临时停车*/
                                sendControl(serNO_park, machine.getMachineNO(), ControlTypeConstant.CONTROL_TYPE_CONTROL, ControlTypeConstant.CONTROL_TYPE_PARKRIDE, "", machine, false, -1, info.getUserId(), "超远距离借车自动临停");
                            } else {
                                /**控制车辆上锁*/
                                sendControl(serNO_park, machine.getMachineNO(), ControlTypeConstant.CONTROL_TYPE_CONTROL, ControlTypeConstant.CONTROL_TYPE_LOCK, "", machine, false, -1, info.getUserId(), "超远距离借车自动临停");
                            }
                            Park park = new Park();
                            park.setAccountId(info.getAccountId());
                            park.setUserId(info.getUserId());
                            park.setMachineId(info.getMachineId());
                            park.setStartTime(DateTimeUtil.getNowTime());
                            park.setRemark("超远距离借车自动临停");
                            parkService.insert(park);

                            machineOpLogService.insertSingle(MachineOpLog.builder()
                                    .accountId(machine.getAccountId())
                                    .machineId(machine.getMachineId())
                                    .machineNO(machine.getMachineNO())
                                    .userCode(machine.getUserCode())
                                    .operation("超远距离借车自动临停")
                                    .opUser("系统")
                                    .opUserPhone("-1")
                                    .opPlatform(OperationPlatform.CLIENT.code)
                                    .result(true)
                                    .detail("超远距离借车自动临停")
                                    .opTime(LocalDateTime.now())
                                    .build()
                            );
                        }
                        // 运营区外借车
                        String outOfRangeFlag = redisService.get(String.format(RedisConstant.OUT_OF_RANGE_BORROW_BIKE, machine.getMachineId()));
                        if (Objects.equals(outOfRangeFlag,"1")){
                            Map<String,Object> paramMap = new HashMap<String,Object>(){{
                               put("accountId",machine.getAccountId());
                               put("paramKey",AccountConfigExtConstant.POWER_tIME);
                            }};
                            AccountConfigExt accountConfigExt = accountConfigExtDao.getByKey(paramMap);
                            int powerTime = Integer.parseInt(accountConfigExt.getParamValue());
                            String serNO_power = UUID.randomUUID().toString();
                            sendControl(serNO_power, machine.getMachineNO(), ControlTypeConstant.CONTROL_TYPE_CONTROL,
                                    ControlTypeConstant.CONTROL_TYPE_UNLOCK, "", machine, false, -1, info.getUserId(),
                                    "运营区外借车临时通电");

                            TempPowerMsg msg = new TempPowerMsg();
                            msg.setMachineNO(machine.getMachineNO());
                            msg.setOrderNO(info.getOrderNO());
                            msg.setStartTime(DateUtil.now());
                            msg.setDurationSec(powerTime * 60);
                            mqProducer.sendToRide(RabbitMQData.queueExchange, RabbitMQData.tempPowerQueue, com.alibaba.fastjson2.JSON.toJSONString(msg));


                            // 业务认为不需要记录到用户临时通电次数
                            // redisService.incr(String.format("TempPower#%s#%s", machineBorrow.getOrderNO(), machine.getMachineNO()), 5 * 60 * 60);

                            //清除出围栏断电标识
                            redisService.del(RedisConstant.REDIS_MACHINE_OUTGEO_PUSH + machine.getMachineNO());
                            machineOpLogService.insertSingle(MachineOpLog.builder()
                                    .accountId(machine.getAccountId())
                                    .machineId(machine.getMachineId())
                                    .machineNO(machine.getMachineNO())
                                    .userCode(machine.getUserCode())
                                    .operation("运营区外借车自动临时上电")
                                    .opUser("系统")
                                    .opUserPhone("-1")
                                    .opPlatform(OperationPlatform.CLIENT.code)
                                    .result(true)
                                    .detail("运营区外借车自动临时上电")
                                    .opTime(LocalDateTime.now())
                                    .build()
                            );
                        }
                    }
                } else {
                    /**开锁失败*/
                    log.info(String.format("[%s]开锁失败", terControlMsg.getData().getSn()));
                }

                if (brtInfo != null) {
                    BorrowReturnTer info = JSONObject.parseObject(brtInfo, BorrowReturnTer.class);
                    if (info.getType() == 0) {//正常接还车
                        if (ControlTypeConstant.CONTROL_TYPE_SUCC.equals(controlRet)) {
                            /**借还车信息推送到mq*/
                            send(info.getAccountId(), info.getUserId(), info.getMachineId(), null, GatewayProtocol.MQ_MSG_ID_RSP_SUCCESS,
                                    MachineStateConstant.MACHINE_TYPE_BORROW, GatewayProtocol.MQ_MSG_ID_AROUND_BR_RSP_PUSH);
                        } else {
                            /**借还车信息推送到mq*/
                            send(info.getAccountId(), info.getUserId(), info.getMachineId(), null, GatewayProtocol.MQ_MSG_ID_RSP_FAIL,
                                    MachineStateConstant.MACHINE_TYPE_BORROW, GatewayProtocol.MQ_MSG_ID_AROUND_BR_RSP_PUSH);

                        }
                    }
                }

            }
        } else {
            log.error("异常信息，找不到对应流水信息=");

            /**控制终端重新上锁*/
        }
        redisService.del(RedisConstant.ORDER_WEB_KEY_PREFIX + serNO);
        /**删除内存信息*/
    }

    public Integer getAccountUserType(AccountUser accountUser, Integer orderSource) {
        //品牌、加盟商、区域代理商
        int accountUserType = accountUser.getAccountType();
        if (OrderLogConstant.fromMain(orderSource)) {
            Integer subRoleType = accountUser.getSubRoleType();
            /*账号类型转换*/
            //运维管理员
            if (subRoleType == 1) {
                accountUserType = 4;
                //运维人员
            } else if (subRoleType == 2) {
                accountUserType = 5;
            } else {
                accountUserType = accountUser.getSubRoleType();
            }
        }
        return accountUserType;
    }

    @Override
    public void sendToQueue(String msg) {
        mQProducer.sendToAi(RabbitMQData.aiQueue, msg);
    }

    @Override
    public void sendPushMsg(String queueKey, String msg) {
        mQProducer.sendToRide(GatewayProtocol.EXCHANGE_RIDE_PUSH, queueKey, msg);
    }

    @Override
    public void send(String exchange, String queueKey, String msgId, String feedback, String msg) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("msgId", msgId);
        jsonObject.put("feedback", feedback);
        jsonObject.put("data", msg);
        mQProducer.sendWithTtl(exchange, queueKey, RabbitMQData.mq_ttl, jsonObject.toJSONString());
    }

    @Override
    public void send(Integer accountId, Integer userId, Integer machineId, Integer orderSource, Integer result, Integer type, Integer msgId) {
        BorrowFrequency borrowFrequency = new BorrowFrequency();
        borrowFrequency.setAccountId(accountId);
        borrowFrequency.setAddTime(new Date());
        borrowFrequency.setMachineId(machineId);
        borrowFrequency.setOrderSource(orderSource);
        ParkMachine p = parkMachineService.getByMachineId(machineId);
        if (p != null) {
            borrowFrequency.setParkPointId(p.getParkPointId());
        }
        borrowFrequency.setResult(result);
        borrowFrequency.setType(type);
        borrowFrequency.setUserId(userId);

        MqData mqData = new MqData();
        mqData.setFeedback(RabbitMQData.aiQueue);
        mqData.setMsgId(msgId);
        mqData.setData(borrowFrequency);
        /**放入内存，定时推送*/
        SystemData.pushList.add(mqData);
    }

    @Override
    public void sendErrorMsg(Machine machine, Integer userId, Integer type, String error, String orderNO, Integer parkPointId, String message, String remark) {
        ErrorMsg errorMsg = new ErrorMsg();
        errorMsg.setAccountId(machine.getAccountId());
        errorMsg.setAddTime(new Date());
        errorMsg.setError(error);
        errorMsg.setMachineId(machine.getMachineId());
        errorMsg.setMachineNO(machine.getMachineNO());
        errorMsg.setOrderNO(orderNO);
        errorMsg.setType(type);
        errorMsg.setUserCode(machine.getUserCode());
        errorMsg.setUserId(userId);
        errorMsg.setParkPointId(parkPointId);
        errorMsg.setRemark(remark);
        errorMsg.setMessage(message);
        MqData errorData = new MqData();
        errorData.setData(errorMsg);
        errorData.setFeedback(RabbitMQData.aiQueue);
        errorData.setMsgId(GatewayProtocol.MQ_MSG_ID_AROUND_ERROR_MSG_PUSH);
        /**放入内存，定时推送*/
        SystemData.pushList.add(errorData);
    }

    @Override
    public void handelTlvs(String data) {
        TerInfoUpload terInfoUpload = JSON.parseObject(data, TerInfoUpload.class);
        if (terInfoUpload.getEventType() == 164) {
            handelWeight(terInfoUpload);
            return;
        }
        if (terInfoUpload.getEventType() != 50) {
            return;
        }
        log.info("一键还车解析对象=" + terInfoUpload);
        if (terInfoUpload.getEventType() != 50) {
            return;
        }
        Machine machine = machineService.getByMachineNO(terInfoUpload.getMno());
        if (machine == null) {
            return;
        }
        MachineBorrow machineBorrow = machineBorrowService.getByMachineId(machine.getMachineId());
        if (machineBorrow == null) {
            return;
        }
        /**站点判断*/
        Integer parkPointId = parkPointService
                .checkInParkPoint(machine.getAccountId(), new Point(terInfoUpload.getLon(), terInfoUpload.getLat()), machine.getMachineId(), null);
        if (parkPointId == null) {
            log.info("设备不在站点" + machineBorrow.getOrderNO());
            String serNO = UUID.randomUUID().toString();
            sendControl(serNO, machine.getMachineNO(), ControlTypeConstant.CONTROL_TYPE_VOICE, ControlTypeConstant.CONTROL_TYPE_VOICE_NOT_IN_PARKPOINT, "", machine, false, -1, machineBorrow.getUserId(), "设备不在站点语音下发");
            return;
        }
        //tlvs 附加参数
        List<WA206TLV> tlvs = terInfoUpload.getTlvs();
        /**附加参数*/
        if (tlvs != null && !tlvs.isEmpty()) {
            JSONArray jsonArray = JSONObject.parseObject(data).getJSONArray("tlvs");
            /***/
            for (int i = 0; i < jsonArray.size(); i++) {
                String tmp = jsonArray.getString(i);
                Integer type = jsonArray.getJSONObject(i).getInteger("type");
                if (WA206TLV.EX_TLV_TYPE_RETURN == type) {
                    TlvReturnBike tlvReturnBike = JSON.parseObject(tmp, TlvReturnBike.class);
                } else if (WA206TLV.EX_TLV_TYPE_HELMET == type || WA206TLV.EX_TLV_TYPE_NOMAL_HELMET == type || WA206TLV.EX_TLV_TYPE_BLE_HELMET == type) {
                    Integer bleState = 0;
                    Integer sw = 0;
                    if (WA206TLV.EX_TLV_TYPE_HELMET == type) {
                        TlvHelmet tlvHelmet = JSON.parseObject(tmp, TlvHelmet.class);
                        sw = tlvHelmet.sw;
                        if (ObjectUtil.statusParse(2, sw)) {
                            bleState = bleState + 1;
                        }
                        if (ObjectUtil.statusParse(1, sw)) {
                            bleState = bleState + 2;
                        }
                        if (ObjectUtil.statusParse(5, sw)) {
                            bleState = bleState + 4;
                        }
                        if (ObjectUtil.statusParse(6, sw)) {
                            bleState = bleState + 8;
                        }
                    } else if (WA206TLV.EX_TLV_TYPE_NOMAL_HELMET == type) {
                        TlvNormalHelmet tlvHelmet = JSON.parseObject(tmp, TlvNormalHelmet.class);
                        sw = tlvHelmet.sw;
                        if (ObjectUtil.statusParse(1, sw)) {
                            bleState = bleState + 1;
                        }
                        if (ObjectUtil.statusParse(2, sw)) {
                            bleState = bleState + 2;
                        }
                        if (ObjectUtil.statusParse(3, sw)) {
                            bleState = bleState + 4;
                        }
                        if (ObjectUtil.statusParse(4, sw)) {
                            bleState = bleState + 8;
                        }
                    } else if (WA206TLV.EX_TLV_TYPE_BLE_HELMET == type) {
                        TlvBleHelmet tlvBleHelmet = JSON.parseObject(tmp, TlvBleHelmet.class);

                        sw = tlvBleHelmet.sw;
                        BleHelmet bleHelmet = new BleHelmet();
                        bleHelmet.setSoc(tlvBleHelmet.soc);
                        /***/
                        String mac = tlvBleHelmet.mac;
                        mac = ObjectUtil.macCheck(mac);
                        bleHelmet.setHelmetMac(mac);
                        bleHelmet.setBatDt(new Date());
                        bleHelmetDao.edit(bleHelmet);
                        if (ObjectUtil.statusParse(1, sw)) {
                            bleState = bleState + 1;
                        }
                        if (ObjectUtil.statusParse(2, sw)) {
                            bleState = bleState + 2;
                        }
                        if (ObjectUtil.statusParse(0, sw)) {
                            bleState = bleState + 4;
                        }
                    }

                    Dispatch dispatch = machineService.intelHelmetCheck(machine.getMachineNO(), bleState);
                    boolean result = false;
                    if (dispatch == null) {
                        result = true;
                    }
                    //boolean result= ObjectUtil.statusParse(0,bleState);
                    if (!result) {
                        log.info("设备头盔锁条件不满足" + machineBorrow.getOrderNO());
                        String serNO = UUID.randomUUID().toString();
                        sendControl(serNO, machine.getMachineNO(), ControlTypeConstant.CONTROL_TYPE_VOICE, ControlTypeConstant.CONTROL_TYPE_VOICE_HELMET, "", machine, false, -1, machineBorrow.getUserId(), "设备头盔锁条件不满足语音下发");
                        return;
                    }
                } else if (WA206TLV.EX_TLV_TYPE_CAMERA_RET == type) {
                    TlvCameraRet tlvCameraRet = JSON.parseObject(tmp, TlvCameraRet.class);
                    WebcamInfo webcamInfo = new WebcamInfo();
                    webcamInfo.setRet(tlvCameraRet.result);
                    webcamInfo.setPicDir(tlvCameraRet.angle);
                    webcamInfo.setSimilar(tlvCameraRet.similarity);
                    Dispatch dispatch = machineCheckService.checkWebcam(machine.getAccountId(), machine.getMachineNO(), parkPointId, JSON.toJSONString(webcamInfo), 1);
                    if (dispatch != null && dispatch.getType().equals(DisPatchConstant.DISPATCH_SXT)) {
                        log.info("设备摄像头条件不满足" + machineBorrow.getOrderNO());
                        String serNO = UUID.randomUUID().toString();
                        sendControl(serNO, machine.getMachineNO(), ControlTypeConstant.CONTROL_TYPE_VOICE, ControlTypeConstant.CONTROL_TYPE_VOICE_SXT, "", machine, false, -1, machineBorrow.getUserId(), "设备摄像头条件不满足语音下发");
                        return;
                    }
                } else if (WA206TLV.EX_TLV_TYPE_RFID_RET == type) {
                    TlvRfidInfo tlvRfidInfo = JSON.parseObject(tmp, TlvRfidInfo.class);
                    ///RedisConstant.RFID_FAIL_KEY_PREFIX + terInfoUpload.getMno()
                    getValue(RedisConstant.RFID_FAIL_KEY_PREFIX + terInfoUpload.getMno());

                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("ret", tlvRfidInfo.result);
                    Dispatch dispatch = machineCheckService.checkRfid(machine.getAccountId(), machine.getMachineNO(), parkPointId, jsonObject.toJSONString(), 1);
                    if (dispatch != null && dispatch.getType().equals(DisPatchConstant.DISPATCH_RFID)) {
                        log.info("设备rfid条件不满足" + machineBorrow.getOrderNO());
                        String serNO = UUID.randomUUID().toString();
                        sendControl(serNO, machine.getMachineNO(), ControlTypeConstant.CONTROL_TYPE_VOICE, ControlTypeConstant.CONTROL_TYPE_VOICE_FRID, "", machine, false, -1, machineBorrow.getUserId(), "设备rfid条件不满足语音下发");
                        return;
                    }
                } else if (WA206TLV.EX_TLV_TYPE_BLE_RET == type) {
                    TlvBleInfo tlvBleInfo = JSON.parseObject(tmp, TlvBleInfo.class);

                } else if (WA206TLV.EX_TLV_TYPE_ANGLE_INFO == type) {
                    TlvAngleInfo tlvAngleInfo = JSON.parseObject(tmp, TlvAngleInfo.class);
                    getValue(RedisConstant.ANGLE_FAIL_KEY_PREFIX + machine.getMachineId());
                    AccountConfig accountConfig = cacheService.getConfig(machine.getAccountId());
                    Dispatch dispatch = machineService.isVertical(accountConfig, machine, machineBorrow.getUserId(), machineBorrow.getOrderNO(), parkPointId, String.valueOf(tlvAngleInfo.deflectionAngle), 1);
                    if (dispatch != null && dispatch.getType().equals(DisPatchConstant.DISPATCH_VERTICAL)) {
                        log.info("设备垂直停车条件不满足" + machineBorrow.getOrderNO());
                        String serNO = UUID.randomUUID().toString();
                        sendControl(serNO, machine.getMachineNO(), ControlTypeConstant.CONTROL_TYPE_VOICE, ControlTypeConstant.CONTROL_TYPE_VOICE_ANGLE, "", machine, false, -1, machineBorrow.getUserId(), "设备垂直停车条件不满足语音下发");
                        return;
                    }
                }
            }
        }
        //最后在进行还车金额校验
        String serNO = UUID.randomUUID().toString();
        Double money = machineService.returnBike(serNO, machineBorrow.getUserId(), false, new Point(terInfoUpload.getLon(), terInfoUpload.getLat()), 1, true, -1, 0, "cn", null, null);
        if (money != null && money > 0D) {
            log.info("用户余额不足" + machineBorrow.getOrderNO());
            String serNO1 = UUID.randomUUID().toString();
            sendControl(serNO1, machine.getMachineNO(), ControlTypeConstant.CONTROL_TYPE_VOICE, ControlTypeConstant.CONTROL_TYPE_VOICE_LESS_MONEY, "", machine, false, -1, machineBorrow.getUserId(), "用户余额不足语音下发");
            return;
        }
    }


    public void getValue(String key) {
        String tmp = redisService.get(key);
        if (!StringUtils.isEmpty(tmp)) {
            redisService.add(key, String.valueOf(Integer.valueOf(tmp) + 1), 60);
        }
    }

    private void handelWeight(TerInfoUpload terInfoUpload) {
        Machine machine = machineService.getByMachineNO(terInfoUpload.getMno());
        if (machine == null) {
            return;
        }
        MachineBorrow machineBorrow = machineBorrowService.getByMachineId(machine.getMachineId());
        if (machineBorrow == null) {
            return;
        }
        log.info("handelWeight-------->terInfoUpload:{}",JSON.toJSON(terInfoUpload));
        if (CollectionUtils.isEmpty(terInfoUpload.getTlvs())){
            return;
        }
        List<TlvWeight> tlvs = JSONObject.parseArray(terInfoUpload.getTlvs().toString(), TlvWeight.class);
        TlvWeight weight = tlvs.stream().filter(tlv -> Objects.equals(tlv.type, WA206TLV.EX_TLV_TYPE_WEIGHT)).findFirst().orElse(null);

        if (weight == null) {
            return;
        }

        Date now = new Date();

        RideLog rideLog = rideLogService.getByOrderNO(machineBorrow.getOrderNO());
        if (rideLog == null) {
            return;
        }

        if (!userDetailService.shouldLogWeight(machine.getAccountId(), machine.getMachineId())) {
            return;
        }

        userWeightLogService.deleteExcessData(machineBorrow.getUserId());

        createUserWeightLog(machineBorrow, machine, weight, now);
    }

    private void createUserWeightLog(MachineBorrow machineBorrow, Machine machine, TlvWeight weight, Date now) {
        UserWeightLog userWeightLog = new UserWeightLog();
        userWeightLog.setUserId(machineBorrow.getUserId());
        User user = Optional.ofNullable(userService.getByUserId(machineBorrow.getUserId())).orElse(new User());
        Account brand = Optional.ofNullable(accountService.getByAccountId(user.getAccountId())).orElse(new Account());
        Account account = Optional.ofNullable(accountService.getByAccountId(machine.getAccountId())).orElse(new Account());
        MachineFunction machineFunction = Optional.ofNullable(machineFunctionService.get(machine.getMachineId(), MachineStateConstant.MACHINE_TYPE_WEIGHT)).orElse(new MachineFunction());
        userWeightLog.setUsername(user.getName());
        userWeightLog.setPhone(user.getPhone());
        userWeightLog.setBrandId(user.getAccountId());
        userWeightLog.setBrandName(brand.getName());
        userWeightLog.setAccountId(account.getAccountId());
        userWeightLog.setAccountName(account.getName());
        userWeightLog.setMachineType(machineFunction.getFunctionName());
        userWeightLog.setWeight(weight.getWeightBalance());
        userWeightLog.setWeightRange(machineFunction.getFunctionMode());
        userWeightLog.setUserCode(machine.getUserCode());
        userWeightLog.setMachineNo(machine.getMachineNO());
        userWeightLog.setOrderNo(machineBorrow.getOrderNO());
        userWeightLog.setCreateTime(now);
        userWeightLog.setUpdateTime(now);
        userWeightLog.setStatus(1);

        // 计算体重是否有效
        UserDetail userDetail = userDetailService.get(0, machineBorrow.getUserId());
        if (userDetail != null && StrUtil.isNotBlank(userDetail.getValue())) {
            int start = Integer.parseInt(userDetail.getValue()) - 30;
            int end = Integer.parseInt(userDetail.getValue()) + 30;
            if (weight.getWeightBalance() < start || weight.getWeightBalance() >= end) {
                userWeightLog.setStatus(0);
                userWeightLog.setRemark(String.format("有效体重 %s ± 30 kg", userDetail.getValue()));
            }
        }

        userWeightLogService.create(userWeightLog);
    }


}